home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Games / MAME / src / machine / segacrpt.c < prev    next >
C/C++ Source or Header  |  2000-04-23  |  52KB  |  1,112 lines

  1. /******************************************************************************
  2.  
  3.   Sega encryption emulation                                 by Nicola Salmoria
  4.  
  5.  
  6.   Several Sega Z80 games have program ROMs encrypted using a common algorithm
  7.   (but with a different key).
  8.   The hardware used to implement this encryption is either a custom CPU, or an
  9.   epoxy block which probably contains a standard Z80 + PALs.
  10.  
  11.   You can think of the decryption algorithm as a black box which takes as
  12.   input D3, D5, D7, M1, A0, A4, A8 and A12, and returns the decrypted D3, D5
  13.   and D7. [Dn are the data lines, An the address lines, M1 is the Z80 pin which
  14.   tells whether the CPU is accessing data or opcodes]. D0, D1, D3, D4 and D6
  15.   are always unaffected.
  16.  
  17.   We can summarize that using a XOR mask laid out like this:
  18.  
  19.     0 1 2 3 4 5 6 7 8 9 a b c d e f
  20.   0 A A A A A A A A B B B B B B B B
  21.   1 A A A A A A A A B B B B B B B B
  22.   2 C C C C C C C C D D D D D D D D
  23.   3 C C C C C C C C D D D D D D D D
  24.   4 A A A A A A A A B B B B B B B B
  25.   5 A A A A A A A A B B B B B B B B
  26.   6 C C C C C C C C D D D D D D D D
  27.   7 C C C C C C C C D D D D D D D D
  28.   8 D D D D D D D D C C C C C C C C
  29.   9 D D D D D D D D C C C C C C C C
  30.   a B B B B B B B B A A A A A A A A
  31.   b B B B B B B B B A A A A A A A A
  32.   c D D D D D D D D C C C C C C C C
  33.   d D D D D D D D D C C C C C C C C
  34.   e B B B B B B B B A A A A A A A A
  35.   f B B B B B B B B A A A A A A A A
  36.  
  37.   on the left edge you have the most significant nibble of the data, on the top
  38.   edge the least significant nibble. For example, if the input data is 0xc0, it
  39.   will be XORed with D. As you can see, the table is symmetrical, so the 8
  40.   possible combinations of D3, D5 and D7 only require 4 different XOR values.
  41.   Since only D3, D5 and D7 are affected, A, B, C and D can have only these
  42.   values: 0x00, 0x08, 0x20, 0x28, 0x80, 0x88, 0xa0, 0xa8.
  43.   Another important thing to note is that A XOR B XOR C XOR D must always be 0;
  44.   that is, it must cause a permutation. If that weren't the case, there would
  45.   be values impossible to obtain.
  46.  
  47.   We need 32 of these tables, one for every possible combination of M1, A0, A4,
  48.   A8 and A12. However, all the games currently known are full of repetitions
  49.   and only use 6 different tables, the only exceptions being Pengo and Yamato
  50.   which have 7 (but one of them is { 0x00, 0x00, 0x00, 0x00 } ). This is most
  51.   likely a limitation of the hardware.
  52.   Some of the early games are even weaker: of the 6 different tables, they use
  53.   3 for opcodes and 3 for data, and always coupled in the same way.
  54.  
  55.   In all games currently known, only bytes in the memory range 0x0000-0x7fff
  56.   (A15 = 0) are encrypted. My guess is that this was done to allow games to
  57.   copy code to RAM (in the memory range 0x8000-0xffff) and execute it from
  58.   there without the CPU trying to decrypt it and messing everything up.
  59.   However Zaxxon has RAM at 0x6000, and the CPU doesn't seem to interfere with
  60.   it; but it doesn't execute code from there, so it's possible that the CPU is
  61.   encrypting the data while writing it and decrypting it while reading (that
  62.   would seem kind of strange though). Video and sprite RAM and memory mapped
  63.   ports are all placed above 0x8000.
  64.  
  65.   Given its strict limitations, this encryption is reasonably easy to break,
  66.   and very vulnerable to known plaintext attacks.
  67.  
  68.  
  69.  
  70.   Ninja Princess:
  71.  
  72.   there is a (bootleg?) board which has a standard Z80 + 2 bipolar PROMs
  73.   instead of the custom CPU. The encryption table is different from the
  74.   original Ninja Princess; it is actually the same as Flicky.
  75.  
  76.   The first PROM is 32x8 (?) and contains the number (0..5) of the table to
  77.   use depending on M1, A0, A4, A8, A12:
  78.  
  79.   00: 11 00 33 22 00 44 44 00 11 33 33 22 44 44 44 22
  80.   10: 11 55 55 33 44 22 55 22 11 33 55 33 44 44 11 22
  81.  
  82.   The second PROM is 256x4 and contains the 6 different XOR tables:
  83.  
  84.        A  D  B  C  C  B  D  A
  85.   00: 09 09 0A 0A 0A 0A 09 09
  86.   08: 0E 08 0B 0D 0D 0B 08 0E
  87.   10: 0A 0C 0A 0C 0C 0A 0C 0A
  88.   18: 0B 0E 0E 0B 0B 0E 0E 0B
  89.   20: 0C 0C 0F 0F 0F 0F 0C 0C
  90.   28: 08 0D 0B 0E 0E 0B 0D 08
  91.   [the remaining bytes are all 0F]
  92.   bit 3 is not used.
  93.   bits 0-2 is the XOR code inverted (0 = 0xa8, 1 = 0xa0 ... 6 = 0x08 7 = 0x00)
  94.  
  95.   Here is a diagram showing how it works:
  96.  
  97.   data to                             XOR
  98.   decode                             value
  99.                       A ---
  100.   D7  --------------- 0|   |
  101.   D3  --------------- 1|   |
  102.   D5  --------------- 2| P |D
  103.           A --- D      | R |0 ---|>--- D3
  104.   M1  --- 0| P |0 --- 3| O |1 ---|>--- D5
  105.   A0  --- 1| R |1 --- 4| M |2 ---|>--- D7
  106.   A4  --- 2| O |2 --- 5| 2 |3 ---
  107.   A8  --- 3| M |3 --- 6|   |
  108.   A12 --- 4| 1 |4 --- 7|   |
  109.             ---         ---
  110.  
  111.  
  112.   My Hero:
  113.  
  114.   the bootleg does the decryption using a single 256x4 PROM, mapped in the
  115.   obvious way:
  116.  
  117.   data to            XOR
  118.   decode            value
  119.           A ---
  120.   D3  --- 0|   |
  121.   D5  --- 1|   |D
  122.   D7  --- 2| P |0 --- D3
  123.   A0  --- 3| R |1 --- D5
  124.   A4  --- 4| O |2 --- D7
  125.   A8  --- 5| M |3 ---
  126.   A12 --- 6|   |
  127.   M1  --- 7|   |
  128.             ---
  129.  
  130.  
  131.  
  132.   List of encrypted games currently known:
  133.  
  134.  CPU Part #         Game                   Comments
  135.   315-5010      Pengo                  unencrypted version available
  136.   315-5013      Super Zaxxon           used Zaxxon for known plaintext attack
  137.   ???-????      Super Locomotive
  138.   ???-???? M120 Razzmatazz             same key as Ninja Princess
  139.   315-5018      Yamato
  140.   315-5028      Sindbad Mystery
  141.   315-5033      Regulus
  142.   315-5041 M140 Mister Viking
  143.   315-5048      SWAT                   used Bull Fight for k.p.a.
  144.   315-5051      Flicky &
  145.                 Ninja Princess (bootleg)
  146.   ???-????      Water Match            not available yet
  147.   315-5061      Future Spy
  148.   315-5065      Bull Fight
  149.   315-5069      Star Force             game by Tehkan; same key as Super Locomotive
  150.   315-5093      Pitfall II
  151.   315-5098      Ninja Princess         unencrypted version available
  152.   315-5102      Sega Ninja             unencrypted version available
  153.   315-5110      I'm Sorry              used My Hero for k.p.a.
  154.   315-5114      ?? pcb 834-5492        not decoded yet
  155.   315-5115      TeddyBoy Blues
  156.   315-5135      Heavy Metal &
  157.                 Wonder Boy (set 1 & 2; bootlegs?)
  158.   ???-????      My Hero
  159.  
  160.  
  161.   The following games use a different encryption algorithm:
  162.  
  163.   315-5162 4D Warriors            used I'm Sorry for k.p.a.
  164.   315-5177 Wonder Boy (set 3)     not decoded yet
  165.   315-5178 Wonder Boy (set 4)     used Wonder Boy Deluxe for k.p.a.
  166.   ???-???? Gardia                 not decoded yet
  167.  
  168.  
  169.   The following games use another different encryption algorithm, much more
  170.   secure than the previous two, which has not been broken yet. It might be
  171.   similar to the one used in System 16 games.
  172.  
  173.   317-5014?DakkoChan Jansoh
  174.   317-0029 Block Gal              NEC MC8123B 651 packaged like System16's 68000
  175.   317-0030 Perfect Billiards
  176.   317-0043 Wonder Boy Monster Land
  177.   317-0054 Shinobi (sound CPU)    NEC MC8123B 651
  178.   317-0064 Ufo Senshi Yohko Chan
  179.  
  180.  
  181.  
  182.   Some text found in the ROMs:
  183.  
  184.   Super Locomotive SEGA FUKUMURA MIZUNAGA
  185.   Yamato           SECULITY BY M,MIZUNAGA
  186.   Regulus          SECULITY BY SYUICHI,KATAGI
  187.   Mister Viking    SECURITY BY S.KATAGI  CONTROL CHIP M140
  188.   SWAT             SECURITY BY S.KATAGI
  189.   Flicky           SECURITY BY S.KATAGI
  190.   Star Force       STAR FORCE TEHKAN. SECURITY BY SEGA ENTERPRISESE
  191.  
  192. ******************************************************************************/
  193.  
  194. #include "driver.h"
  195.  
  196.  
  197. #ifdef MAME_DEBUG
  198. static void lfkp(int mask)
  199. {
  200.     int A;
  201.     unsigned char *RAM = memory_region(REGION_CPU1);
  202.  
  203.  
  204.     for (A = 0x0000;A < 0x8000-14;A++)
  205.     {
  206.         static char text[] = "INSERT COIN";
  207.         int i;
  208.  
  209.  
  210.         if (    (RAM[A+0] & mask) == (0x21 & mask) &&    /* LD HL,$xxxx */
  211.                 (RAM[A+3] & mask) == (0x11 & mask) &&    /* LD DE,$xxxx */
  212.                 (RAM[A+6] & mask) == (0x01 & mask))        /* LD BC,$xxxx */
  213.         {
  214.             if (    (RAM[A+ 9] & mask) == (0x36 & mask) &&    /* LD (HL),$xx */
  215.                     (RAM[A+11] & mask) == (0xed & mask) &&
  216.                     (RAM[A+12] & mask) == (0xb0 & mask))    /* LDIR */
  217.                 logerror("%04x: hl de bc (hl),xx ldir\n",A);
  218.  
  219.             if (    (RAM[A+ 9] & mask) == (0x77 & mask) &&    /* LD (HL),A */
  220.                     (RAM[A+10] & mask) == (0xed & mask) &&
  221.                     (RAM[A+11] & mask) == (0xb0 & mask))    /* LDIR */
  222.                 logerror("%04x: hl de bc (hl),a ldir\n",A);
  223.  
  224.             if (    (RAM[A+ 9] & mask) == (0xed & mask) &&
  225.                     (RAM[A+10] & mask) == (0xb0 & mask))    /* LDIR */
  226.                 logerror("%04x: hl de bc ldir\n",A);
  227.         }
  228.  
  229.         /* the following can also be PUSH IX, PUSH IY - need better checking */
  230.         if (    (RAM[A+0] & mask) == (0xf5 & mask) &&    /* PUSH AF */
  231.                 (RAM[A+1] & mask) == (0xc5 & mask) &&    /* PUSH BC */
  232.                 (RAM[A+2] & mask) == (0xd5 & mask) &&    /* PUSH DE */
  233.                 (RAM[A+3] & mask) == (0xe5 & mask))        /* PUSH HL */
  234.             logerror("%04x: push af bc de hl\n",A);
  235.  
  236.         if (    (RAM[A+0] & mask) == (0xe1 & mask) &&    /* POP HL */
  237.                 (RAM[A+1] & mask) == (0xd1 & mask) &&    /* POP DE */
  238.                 (RAM[A+2] & mask) == (0xc1 & mask) &&    /* POP BC */
  239.                 (RAM[A+3] & mask) == (0xf1 & mask))        /* POP AF */
  240.             logerror("%04x: pop hl de bc af\n",A);
  241.  
  242.         for (i = 0;i < strlen(text);i++)
  243.             if ((RAM[A+i] & mask) != (text[i] & mask)) break;
  244.         if (i == strlen(text))
  245.             logerror("%04x: INSERT COIN\n",A);
  246.     }
  247. }
  248.  
  249. static void look_for_known_plaintext(void)
  250. {
  251.     lfkp(0x57);
  252. }
  253.  
  254. static void read_table_from_disk(unsigned char *xortable)
  255. {
  256.     FILE *f;
  257.  
  258.  
  259.     f = fopen("table","rb");
  260.  
  261.     if (f) fread(xortable,1,128,f);
  262.  
  263.     fclose(f);
  264. }
  265. #endif
  266.  
  267. static void sega_decode(const unsigned char xortable[32][4])
  268. {
  269.     int A;
  270.     unsigned char *rom = memory_region(REGION_CPU1);
  271.     int diff = memory_region_length(REGION_CPU1) / 2;
  272.  
  273.  
  274.     memory_set_opcode_base(0,rom+diff);
  275.  
  276.     for (A = 0x0000;A < 0x8000;A++)
  277.     {
  278.         int row,col;
  279.         unsigned char src;
  280.  
  281.  
  282.         src = rom[A];
  283.  
  284.         /* pick the translation table from bits 0, 4, 8 and 12 of the address */
  285.         row = (A & 1) + (((A >> 4) & 1) << 1) + (((A >> 8) & 1) << 2) + (((A >> 12) & 1) << 3);
  286.  
  287.         /* pick the offset in the table from bits 3 and 5 of the source data */
  288.         col = ((src >> 3) & 1) + (((src >> 5) & 1) << 1);
  289.         /* the bottom half of the translation table is the mirror image of the top */
  290.         if (src & 0x80) col = 3 - col;
  291.  
  292.         /* decode the opcodes */
  293.         rom[A + diff] = src ^ xortable[2*row][col];
  294.  
  295.         /* decode the data */
  296.         rom[A] = src ^ xortable[2*row+1][col];
  297.  
  298.         if (xortable[2*row][col] == 0xff)    /* table incomplete! (for development) */
  299.             rom[A + diff] = 0x00;
  300.         if (xortable[2*row+1][col] == 0xff)    /* table incomplete! (for development) */
  301.             rom[A] = 0xee;
  302.     }
  303.  
  304.     /* copy the opcodes from the not encrypted part of the ROMs */
  305.     for (A = 0x8000;A < diff;A++)
  306.         rom[A + diff] = rom[A];
  307. }
  308.  
  309.  
  310.  
  311. void pengo_decode(void)
  312. {
  313.     static const unsigned char xortable[32][4] =
  314.     {
  315.         /*       opcode                   data                     address      */
  316.         /*  A    B    C    D         A    B    C    D                           */
  317.         { 0xa0,0x88,0x88,0xa0 }, { 0x28,0xa0,0x28,0xa0 },    /* ...0...0...0...0 */
  318.         { 0x28,0xa0,0x28,0xa0 }, { 0xa0,0x88,0x88,0xa0 },    /* ...0...0...0...1 */
  319.         { 0xa0,0x88,0x00,0x28 }, { 0xa0,0x88,0x00,0x28 },    /* ...0...0...1...0 */
  320.         { 0x08,0x20,0xa8,0x80 }, { 0xa0,0x88,0x88,0xa0 },    /* ...0...0...1...1 */
  321.         { 0x08,0x08,0xa8,0xa8 }, { 0x28,0xa0,0x28,0xa0 },    /* ...0...1...0...0 */
  322.         { 0xa0,0x88,0x00,0x28 }, { 0x08,0x08,0xa8,0xa8 },    /* ...0...1...0...1 */
  323.         { 0xa0,0x88,0x00,0x28 }, { 0xa0,0x88,0x00,0x28 },    /* ...0...1...1...0 */
  324.         { 0xa0,0x88,0x00,0x28 }, { 0x00,0x00,0x00,0x00 },    /* ...0...1...1...1 */
  325.         { 0x88,0x88,0x28,0x28 }, { 0xa0,0x88,0x00,0x28 },    /* ...1...0...0...0 */
  326.         { 0x88,0x88,0x28,0x28 }, { 0x00,0x00,0x00,0x00 },    /* ...1...0...0...1 */
  327.         { 0x08,0x20,0xa8,0x80 }, { 0x08,0x20,0xa8,0x80 },    /* ...1...0...1...0 */
  328.         { 0xa0,0x88,0x88,0xa0 }, { 0xa0,0x88,0x00,0x28 },    /* ...1...0...1...1 */
  329.         { 0x08,0x08,0xa8,0xa8 }, { 0x88,0x88,0x28,0x28 },    /* ...1...1...0...0 */
  330.         { 0x00,0x00,0x00,0x00 }, { 0x88,0x88,0x28,0x28 },    /* ...1...1...0...1 */
  331.         { 0x08,0x20,0xa8,0x80 }, { 0x08,0x20,0xa8,0x80 },    /* ...1...1...1...0 */
  332.         { 0x08,0x08,0xa8,0xa8 }, { 0xa0,0x88,0x00,0x28 }    /* ...1...1...1...1 */
  333.     };
  334.  
  335.  
  336.     sega_decode(xortable);
  337. }
  338.  
  339.  
  340. void szaxxon_decode(void)
  341. {
  342.     static const unsigned char xortable[32][4] =
  343.     {
  344.         /*       opcode                   data                     address      */
  345.         /*  A    B    C    D         A    B    C    D                           */
  346.         { 0x88,0xa0,0xa0,0x88 }, { 0x28,0x28,0x88,0x88 },    /* ...0...0...0...0 */
  347.         { 0x08,0x20,0xa8,0x80 }, { 0x88,0x88,0x28,0x28 },    /* ...0...0...0...1 */
  348.         { 0xa8,0x20,0x80,0x08 }, { 0x20,0xa8,0x20,0xa8 },    /* ...0...0...1...0 */
  349.         { 0x88,0xa0,0xa0,0x88 }, { 0x28,0x28,0x88,0x88 },    /* ...0...0...1...1 */
  350.         { 0x08,0x20,0xa8,0x80 }, { 0x88,0x88,0x28,0x28 },    /* ...0...1...0...0 */
  351.         { 0x88,0xa0,0xa0,0x88 }, { 0x28,0x28,0x88,0x88 },    /* ...0...1...0...1 */
  352.         { 0xa8,0x20,0x80,0x08 }, { 0x20,0xa8,0x20,0xa8 },    /* ...0...1...1...0 */
  353.         { 0x08,0x20,0xa8,0x80 }, { 0x88,0x88,0x28,0x28 },    /* ...0...1...1...1 */
  354.         { 0x08,0x20,0xa8,0x80 }, { 0x88,0x88,0x28,0x28 },    /* ...1...0...0...0 */
  355.         { 0x88,0xa0,0xa0,0x88 }, { 0x28,0x28,0x88,0x88 },    /* ...1...0...0...1 */
  356.         { 0x88,0xa0,0xa0,0x88 }, { 0x28,0x28,0x88,0x88 },    /* ...1...0...1...0 */
  357.         { 0xa8,0x20,0x80,0x08 }, { 0x20,0xa8,0x20,0xa8 },    /* ...1...0...1...1 */
  358.         { 0xa8,0x20,0x80,0x08 }, { 0x20,0xa8,0x20,0xa8 },    /* ...1...1...0...0 */
  359.         { 0xa8,0x20,0x80,0x08 }, { 0x20,0xa8,0x20,0xa8 },    /* ...1...1...0...1 */
  360.         { 0x08,0x20,0xa8,0x80 }, { 0x88,0x88,0x28,0x28 },    /* ...1...1...1...0 */
  361.         { 0x88,0xa0,0xa0,0x88 }, { 0x28,0x28,0x88,0x88 }    /* ...1...1...1...1 */
  362.     };
  363.  
  364.  
  365.     sega_decode(xortable);
  366. }
  367.  
  368.  
  369. void suprloco_decode(void)
  370. {
  371.     static const unsigned char xortable[32][4] =
  372.     {
  373.         /*       opcode                   data                     address      */
  374.         /*  A    B    C    D         A    B    C    D                           */
  375.         { 0x20,0x08,0x80,0xa8 }, { 0xa8,0xa8,0xa8,0xa8 },    /* ...0...0...0...0 */
  376.         { 0x20,0x08,0x80,0xa8 }, { 0xa8,0xa8,0xa8,0xa8 },    /* ...0...0...0...1 */
  377.         { 0x20,0x08,0x80,0xa8 }, { 0xa8,0xa8,0xa8,0xa8 },    /* ...0...0...1...0 */
  378.         { 0x88,0x00,0xa0,0x28 }, { 0xa0,0x88,0x88,0xa0 },    /* ...0...0...1...1 */
  379.         { 0x88,0x00,0xa0,0x28 }, { 0xa0,0x88,0x88,0xa0 },    /* ...0...1...0...0 */
  380.         { 0x20,0x08,0x80,0xa8 }, { 0xa8,0xa8,0xa8,0xa8 },    /* ...0...1...0...1 */
  381.         { 0x88,0x00,0xa0,0x28 }, { 0xa0,0x88,0x88,0xa0 },    /* ...0...1...1...0 */
  382.         { 0x28,0xa0,0x28,0xa0 }, { 0x88,0x88,0x28,0x28 },    /* ...0...1...1...1 */
  383.         { 0x20,0x08,0x80,0xa8 }, { 0xa8,0xa8,0xa8,0xa8 },    /* ...1...0...0...0 */
  384.         { 0x88,0x00,0xa0,0x28 }, { 0xa0,0x88,0x88,0xa0 },    /* ...1...0...0...1 */
  385.         { 0x88,0x00,0xa0,0x28 }, { 0xa0,0x88,0x88,0xa0 },    /* ...1...0...1...0 */
  386.         { 0x20,0x08,0x80,0xa8 }, { 0xa8,0xa8,0xa8,0xa8 },    /* ...1...0...1...1 */
  387.         { 0x88,0x00,0xa0,0x28 }, { 0xa0,0x88,0x88,0xa0 },    /* ...1...1...0...0 */
  388.         { 0x28,0xa0,0x28,0xa0 }, { 0x88,0x88,0x28,0x28 },    /* ...1...1...0...1 */
  389.         { 0x20,0x08,0x80,0xa8 }, { 0xa8,0xa8,0xa8,0xa8 },    /* ...1...1...1...0 */
  390.         { 0x88,0x00,0xa0,0x28 }, { 0xa0,0x88,0x88,0xa0 }    /* ...1...1...1...1 */
  391.     };
  392.  
  393.  
  394.     sega_decode(xortable);
  395. }
  396.  
  397.  
  398. void yamato_decode(void)
  399. {
  400.     static const unsigned char xortable[32][4] =
  401.     {
  402.         /*       opcode                   data                     address      */
  403.         /*  A    B    C    D         A    B    C    D                           */
  404.         { 0x88,0xa0,0x28,0x00 }, { 0x88,0xa0,0xa0,0x88 },    /* ...0...0...0...0 */
  405.         { 0x20,0xa8,0x08,0x80 }, { 0x88,0xa0,0xa0,0x88 },    /* ...0...0...0...1 */
  406.         { 0x88,0xa0,0xa0,0x88 }, { 0x88,0xa0,0xa0,0x88 },    /* ...0...0...1...0 */
  407.         { 0x88,0xa0,0xa0,0x88 }, { 0x20,0xa8,0x08,0x80 },    /* ...0...0...1...1 */
  408.         { 0x88,0xa0,0x28,0x00 }, { 0x88,0xa0,0x28,0x00 },    /* ...0...1...0...0 */
  409.         { 0x88,0xa0,0xa0,0x88 }, { 0x88,0xa0,0xa0,0x88 },    /* ...0...1...0...1 */
  410.         { 0x20,0xa8,0x08,0x80 }, { 0x20,0xa8,0x08,0x80 },    /* ...0...1...1...0 */
  411.         { 0x88,0xa0,0xa0,0x88 }, { 0x88,0xa0,0xa0,0x88 },    /* ...0...1...1...1 */
  412.         { 0x20,0xa8,0x08,0x80 }, { 0x88,0xa0,0x28,0x00 },    /* ...1...0...0...0 */
  413.         { 0x20,0xa8,0x08,0x80 }, { 0x28,0x28,0x88,0x88 },    /* ...1...0...0...1 */
  414.         { 0xa0,0x28,0xa0,0x28 }, { 0x20,0xa8,0x08,0x80 },    /* ...1...0...1...0 */
  415.         { 0x28,0x28,0x88,0x88 }, { 0x20,0xa8,0x08,0x80 },    /* ...1...0...1...1 */
  416.         { 0x20,0xa8,0x08,0x80 }, { 0x88,0xa0,0x28,0x00 },    /* ...1...1...0...0 */
  417.         { 0x88,0xa0,0x28,0x00 }, { 0x88,0xa0,0x28,0x00 },    /* ...1...1...0...1 */
  418.         { 0xa0,0x28,0xa0,0x28 }, { 0x88,0x00,0xa0,0x28 },    /* ...1...1...1...0 */
  419.         { 0x20,0xa8,0x08,0x80 }, { 0x00,0x00,0x00,0x00 }    /* ...1...1...1...1 */
  420.     };
  421.  
  422.  
  423.     sega_decode(xortable);
  424. }
  425.  
  426.  
  427. void sindbadm_decode(void)
  428. {
  429.     static const unsigned char xortable[32][4] =
  430.     {
  431.         /*       opcode                   data                     address      */
  432.         /*  A    B    C    D         A    B    C    D                           */
  433.         { 0x28,0xa0,0x28,0xa0 }, { 0x88,0x88,0x28,0x28 },    /* ...0...0...0...0 */
  434.         { 0xa8,0xa8,0xa8,0xa8 }, { 0x00,0x28,0xa0,0x88 },    /* ...0...0...0...1 */
  435.         { 0xa8,0xa8,0xa8,0xa8 }, { 0x00,0x28,0xa0,0x88 },    /* ...0...0...1...0 */
  436.         { 0x28,0xa0,0x28,0xa0 }, { 0x88,0x88,0x28,0x28 },    /* ...0...0...1...1 */
  437.         { 0xa8,0x80,0x80,0xa8 }, { 0xa0,0x28,0x88,0x00 },    /* ...0...1...0...0 */
  438.         { 0x28,0xa0,0x28,0xa0 }, { 0x88,0x88,0x28,0x28 },    /* ...0...1...0...1 */
  439.         { 0xa8,0xa8,0xa8,0xa8 }, { 0x00,0x28,0xa0,0x88 },    /* ...0...1...1...0 */
  440.         { 0xa8,0xa8,0xa8,0xa8 }, { 0x00,0x28,0xa0,0x88 },    /* ...0...1...1...1 */
  441.         { 0x28,0xa0,0x28,0xa0 }, { 0x88,0x88,0x28,0x28 },    /* ...1...0...0...0 */
  442.         { 0x28,0xa0,0x28,0xa0 }, { 0x88,0x88,0x28,0x28 },    /* ...1...0...0...1 */
  443.         { 0xa8,0xa8,0xa8,0xa8 }, { 0x00,0x28,0xa0,0x88 },    /* ...1...0...1...0 */
  444.         { 0xa8,0xa8,0xa8,0xa8 }, { 0x00,0x28,0xa0,0x88 },    /* ...1...0...1...1 */
  445.         { 0x28,0xa0,0x28,0xa0 }, { 0x88,0x88,0x28,0x28 },    /* ...1...1...0...0 */
  446.         { 0xa8,0x80,0x80,0xa8 }, { 0xa0,0x28,0x88,0x00 },    /* ...1...1...0...1 */
  447.         { 0x28,0xa0,0x28,0xa0 }, { 0x88,0x88,0x28,0x28 },    /* ...1...1...1...0 */
  448.         { 0x28,0xa0,0x28,0xa0 }, { 0x88,0x88,0x28,0x28 }    /* ...1...1...1...1 */
  449.     };
  450.  
  451.  
  452.     sega_decode(xortable);
  453. }
  454.  
  455.  
  456. void regulus_decode(void)
  457. {
  458.     static const unsigned char xortable[32][4] =
  459.     {
  460.         /*       opcode                   data                     address      */
  461.         /*  A    B    C    D         A    B    C    D                           */
  462.         { 0x28,0x00,0x88,0xa0 }, { 0x88,0x88,0x28,0x28 },    /* ...0...0...0...0 */
  463.         { 0x28,0x00,0x88,0xa0 }, { 0x28,0xa0,0x28,0xa0 },    /* ...0...0...0...1 */
  464.         { 0x88,0x88,0x28,0x28 }, { 0x88,0x00,0xa0,0x28 },    /* ...0...0...1...0 */
  465.         { 0x88,0x00,0xa0,0x28 }, { 0x28,0xa0,0x28,0xa0 },    /* ...0...0...1...1 */
  466.         { 0x28,0x00,0x88,0xa0 }, { 0x88,0x88,0x28,0x28 },    /* ...0...1...0...0 */
  467.         { 0x88,0x88,0x28,0x28 }, { 0x88,0x88,0x28,0x28 },    /* ...0...1...0...1 */
  468.         { 0x88,0x00,0xa0,0x28 }, { 0x88,0x00,0xa0,0x28 },    /* ...0...1...1...0 */
  469.         { 0xa0,0x88,0x88,0xa0 }, { 0xa0,0x88,0x88,0xa0 },    /* ...0...1...1...1 */
  470.         { 0x80,0xa8,0x20,0x08 }, { 0x28,0x00,0x88,0xa0 },    /* ...1...0...0...0 */
  471.         { 0x28,0xa0,0x28,0xa0 }, { 0x28,0x00,0x88,0xa0 },    /* ...1...0...0...1 */
  472.         { 0x80,0xa8,0x20,0x08 }, { 0x80,0xa8,0x20,0x08 },    /* ...1...0...1...0 */
  473.         { 0x28,0xa0,0x28,0xa0 }, { 0x80,0xa8,0x20,0x08 },    /* ...1...0...1...1 */
  474.         { 0xa0,0x88,0x88,0xa0 }, { 0x28,0x00,0x88,0xa0 },    /* ...1...1...0...0 */
  475.         { 0x80,0xa8,0x20,0x08 }, { 0xa0,0x88,0x88,0xa0 },    /* ...1...1...0...1 */
  476.         { 0xa0,0x88,0x88,0xa0 }, { 0x80,0xa8,0x20,0x08 },    /* ...1...1...1...0 */
  477.         { 0xa0,0x88,0x88,0xa0 }, { 0xa0,0x88,0x88,0xa0 }    /* ...1...1...1...1 */
  478.     };
  479.  
  480.  
  481.     sega_decode(xortable);
  482. }
  483.  
  484.  
  485. void mrviking_decode(void)
  486. {
  487.     static const unsigned char xortable[32][4] =
  488.     {
  489.         /*       opcode                   data                     address      */
  490.         /*  A    B    C    D         A    B    C    D                           */
  491.         { 0x28,0xa0,0x28,0xa0 }, { 0x88,0x88,0x28,0x28 },    /* ...0...0...0...0 */
  492.         { 0x88,0x00,0xa0,0x28 }, { 0x88,0x88,0x28,0x28 },    /* ...0...0...0...1 */
  493.         { 0x28,0x00,0x88,0xa0 }, { 0x28,0xa0,0x28,0xa0 },    /* ...0...0...1...0 */
  494.         { 0x88,0x00,0xa0,0x28 }, { 0x88,0x00,0xa0,0x28 },    /* ...0...0...1...1 */
  495.         { 0x28,0x00,0x88,0xa0 }, { 0x88,0x88,0x28,0x28 },    /* ...0...1...0...0 */
  496.         { 0x88,0x88,0x28,0x28 }, { 0x28,0xa0,0x28,0xa0 },    /* ...0...1...0...1 */
  497.         { 0xa0,0x88,0x88,0xa0 }, { 0x28,0x00,0x88,0xa0 },    /* ...0...1...1...0 */
  498.         { 0xa0,0x88,0x88,0xa0 }, { 0xa0,0x88,0x88,0xa0 },    /* ...0...1...1...1 */
  499.         { 0x88,0x88,0x28,0x28 }, { 0x88,0x88,0x28,0x28 },    /* ...1...0...0...0 */
  500.         { 0x88,0x00,0xa0,0x28 }, { 0x88,0x88,0x28,0x28 },    /* ...1...0...0...1 */
  501.         { 0xa0,0x88,0x00,0x28 }, { 0x28,0x00,0x88,0xa0 },    /* ...1...0...1...0 */
  502.         { 0xa0,0x88,0x00,0x28 }, { 0x88,0x00,0xa0,0x28 },    /* ...1...0...1...1 */
  503.         { 0x28,0x00,0x88,0xa0 }, { 0xa0,0x88,0x00,0x28 },    /* ...1...1...0...0 */
  504.         { 0xa0,0x88,0x00,0x28 }, { 0xa0,0x88,0x00,0x28 },    /* ...1...1...0...1 */
  505.         { 0xa0,0x88,0x88,0xa0 }, { 0x28,0x00,0x88,0xa0 },    /* ...1...1...1...0 */
  506.         { 0xa0,0x88,0x00,0x28 }, { 0xa0,0x88,0x88,0xa0 }    /* ...1...1...1...1 */
  507.     };
  508.  
  509.  
  510.     sega_decode(xortable);
  511. }
  512.  
  513.  
  514. void swat_decode(void)
  515. {
  516.     static const unsigned char xortable[32][4] =
  517.     {
  518.         /*       opcode                   data                     address      */
  519.         /*  A    B    C    D         A    B    C    D                           */
  520.         { 0x88,0x00,0xa0,0x28 }, { 0xa0,0xa0,0xa0,0xa0 },    /* ...0...0...0...0 */
  521.         { 0x88,0x00,0xa0,0x28 }, { 0x88,0xa0,0xa0,0x88 },    /* ...0...0...0...1 */
  522.         { 0xa0,0x88,0x00,0x28 }, { 0x88,0x00,0xa0,0x28 },    /* ...0...0...1...0 */
  523.         { 0xa0,0xa0,0xa0,0xa0 }, { 0x88,0x00,0xa0,0x28 },    /* ...0...0...1...1 */
  524.         { 0x28,0x28,0x88,0x88 }, { 0xa0,0xa0,0xa0,0xa0 },    /* ...0...1...0...0 */
  525.         { 0x88,0xa0,0xa0,0x88 }, { 0x28,0x28,0x88,0x88 },    /* ...0...1...0...1 */
  526.         { 0xa0,0x88,0x00,0x28 }, { 0xa0,0xa0,0xa0,0xa0 },    /* ...0...1...1...0 */
  527.         { 0x28,0x28,0x88,0x88 }, { 0xa0,0xa0,0xa0,0xa0 },    /* ...0...1...1...1 */
  528.         { 0xa0,0x88,0x00,0x28 }, { 0xa0,0x88,0x00,0x28 },    /* ...1...0...0...0 */
  529.         { 0xa0,0x28,0xa0,0x28 }, { 0x88,0xa0,0xa0,0x88 },    /* ...1...0...0...1 */
  530.         { 0xa0,0x28,0xa0,0x28 }, { 0xa0,0x28,0xa0,0x28 },    /* ...1...0...1...0 */
  531.         { 0xa0,0x28,0xa0,0x28 }, { 0xa0,0x28,0xa0,0x28 },    /* ...1...0...1...1 */
  532.         { 0xa0,0x88,0x00,0x28 }, { 0xa0,0x88,0x00,0x28 },    /* ...1...1...0...0 */
  533.         { 0x88,0xa0,0xa0,0x88 }, { 0x28,0x28,0x88,0x88 },    /* ...1...1...0...1 */
  534.         { 0xa0,0xa0,0xa0,0xa0 }, { 0xa0,0x88,0x00,0x28 },    /* ...1...1...1...0 */
  535.         { 0x28,0x28,0x88,0x88 }, { 0xa0,0xa0,0xa0,0xa0 }    /* ...1...1...1...1 */
  536.     };
  537.  
  538.  
  539.     sega_decode(xortable);
  540. }
  541.  
  542.  
  543. void flicky_decode(void)
  544. {
  545.     static const unsigned char xortable[32][4] =
  546.     {
  547.         /*       opcode                   data                     address      */
  548.         /*  A    B    C    D         A    B    C    D                           */
  549.         { 0x08,0x80,0x20,0xa8 }, { 0xa0,0x88,0x88,0xa0 },    /* ...0...0...0...0 */
  550.         { 0x80,0x08,0x80,0x08 }, { 0x88,0x88,0x28,0x28 },    /* ...0...0...0...1 */
  551.         { 0xa0,0x88,0x88,0xa0 }, { 0x28,0x00,0x00,0x28 },    /* ...0...0...1...0 */
  552.         { 0x28,0x00,0x00,0x28 }, { 0xa0,0x88,0x88,0xa0 },    /* ...0...0...1...1 */
  553.         { 0x08,0x80,0x20,0xa8 }, { 0x80,0x08,0x80,0x08 },    /* ...0...1...0...0 */
  554.         { 0x80,0x08,0x80,0x08 }, { 0x88,0x88,0x28,0x28 },    /* ...0...1...0...1 */
  555.         { 0x28,0x00,0x00,0x28 }, { 0x28,0x00,0x00,0x28 },    /* ...0...1...1...0 */
  556.         { 0x28,0x00,0x00,0x28 }, { 0x88,0x88,0x28,0x28 },    /* ...0...1...1...1 */
  557.         { 0x08,0x80,0x20,0xa8 }, { 0xa8,0x80,0x08,0x20 },    /* ...1...0...0...0 */
  558.         { 0xa8,0x80,0x08,0x20 }, { 0x80,0x08,0x80,0x08 },    /* ...1...0...0...1 */
  559.         { 0x28,0x00,0x00,0x28 }, { 0x88,0x88,0x28,0x28 },    /* ...1...0...1...0 */
  560.         { 0xa8,0x80,0x08,0x20 }, { 0x88,0x88,0x28,0x28 },    /* ...1...0...1...1 */
  561.         { 0x08,0x80,0x20,0xa8 }, { 0x80,0x08,0x80,0x08 },    /* ...1...1...0...0 */
  562.         { 0xa8,0x80,0x08,0x20 }, { 0x80,0x08,0x80,0x08 },    /* ...1...1...0...1 */
  563.         { 0x28,0x00,0x00,0x28 }, { 0x28,0x00,0x00,0x28 },    /* ...1...1...1...0 */
  564.         { 0x08,0x80,0x20,0xa8 }, { 0x88,0x88,0x28,0x28 }    /* ...1...1...1...1 */
  565.     };
  566.  
  567.  
  568.     sega_decode(xortable);
  569. }
  570.  
  571.  
  572. void futspy_decode(void)
  573. {
  574.     static const unsigned char xortable[32][4] =
  575.     {
  576.         /*       opcode                   data                     address      */
  577.         /*  A    B    C    D         A    B    C    D                           */
  578.         { 0x28,0x00,0x00,0x28 }, { 0x28,0x00,0x00,0x28 },    /* ...0...0...0...0 */
  579.         { 0x80,0x08,0x80,0x08 }, { 0x08,0x80,0x20,0xa8 },    /* ...0...0...0...1 */
  580.         { 0x80,0x08,0x80,0x08 }, { 0x08,0x80,0x20,0xa8 },    /* ...0...0...1...0 */
  581.         { 0xa0,0x88,0x00,0x28 }, { 0x20,0x20,0x80,0x80 },    /* ...0...0...1...1 */
  582.         { 0x28,0x00,0x00,0x28 }, { 0x88,0x88,0x88,0x88 },    /* ...0...1...0...0 */
  583.         { 0x80,0x08,0x80,0x08 }, { 0x08,0x80,0x20,0xa8 },    /* ...0...1...0...1 */
  584.         { 0x80,0x08,0x80,0x08 }, { 0x20,0x20,0x80,0x80 },    /* ...0...1...1...0 */
  585.         { 0x20,0x20,0x80,0x80 }, { 0x08,0x80,0x20,0xa8 },    /* ...0...1...1...1 */
  586.         { 0x88,0x88,0x88,0x88 }, { 0x28,0x00,0x00,0x28 },    /* ...1...0...0...0 */
  587.         { 0x80,0x08,0x80,0x08 }, { 0xa0,0x88,0x00,0x28 },    /* ...1...0...0...1 */
  588.         { 0x20,0x20,0x80,0x80 }, { 0x08,0x80,0x20,0xa8 },    /* ...1...0...1...0 */
  589.         { 0x80,0x08,0x80,0x08 }, { 0x20,0x20,0x80,0x80 },    /* ...1...0...1...1 */
  590.         { 0x88,0x88,0x88,0x88 }, { 0x88,0x88,0x88,0x88 },    /* ...1...1...0...0 */
  591.         { 0x80,0x08,0x80,0x08 }, { 0x08,0x80,0x20,0xa8 },    /* ...1...1...0...1 */
  592.         { 0x80,0x08,0x80,0x08 }, { 0x28,0x00,0x00,0x28 },    /* ...1...1...1...0 */
  593.         { 0x20,0x20,0x80,0x80 }, { 0xa0,0x88,0x00,0x28 }    /* ...1...1...1...1 */
  594.     };
  595.  
  596.  
  597.     sega_decode(xortable);
  598. }
  599.  
  600.  
  601. void bullfgtj_decode(void)
  602. {
  603.     static const unsigned char xortable[32][4] =
  604.     {
  605.         /*       opcode                   data                     address      */
  606.         /*  A    B    C    D         A    B    C    D                           */
  607.         { 0xa0,0xa0,0x00,0x00 }, { 0x80,0xa8,0x20,0x08 },    /* ...0...0...0...0 */
  608.         { 0x20,0x20,0x20,0x20 }, { 0x20,0x20,0x20,0x20 },    /* ...0...0...0...1 */
  609.         { 0xa0,0xa0,0x00,0x00 }, { 0x08,0x20,0x20,0x08 },    /* ...0...0...1...0 */
  610.         { 0x88,0x00,0x88,0x00 }, { 0x88,0x00,0x88,0x00 },    /* ...0...0...1...1 */
  611.         { 0xa0,0xa0,0x00,0x00 }, { 0x20,0x20,0x20,0x20 },    /* ...0...1...0...0 */
  612.         { 0x28,0xa0,0x00,0x88 }, { 0x20,0x20,0x20,0x20 },    /* ...0...1...0...1 */
  613.         { 0xa0,0xa0,0x00,0x00 }, { 0x08,0x20,0x20,0x08 },    /* ...0...1...1...0 */
  614.         { 0x88,0x00,0x88,0x00 }, { 0x88,0x00,0x88,0x00 },    /* ...0...1...1...1 */
  615.         { 0x28,0xa0,0x00,0x88 }, { 0xa0,0xa0,0x00,0x00 },    /* ...1...0...0...0 */
  616.         { 0x88,0x00,0x88,0x00 }, { 0x80,0xa8,0x20,0x08 },    /* ...1...0...0...1 */
  617.         { 0x28,0xa0,0x00,0x88 }, { 0x08,0x20,0x20,0x08 },    /* ...1...0...1...0 */
  618.         { 0x28,0xa0,0x00,0x88 }, { 0x80,0xa8,0x20,0x08 },    /* ...1...0...1...1 */
  619.         { 0x20,0x20,0x20,0x20 }, { 0x20,0x20,0x20,0x20 },    /* ...1...1...0...0 */
  620.         { 0x88,0x00,0x88,0x00 }, { 0x20,0x20,0x20,0x20 },    /* ...1...1...0...1 */
  621.         { 0x08,0x20,0x20,0x08 }, { 0x80,0xa8,0x20,0x08 },    /* ...1...1...1...0 */
  622.         { 0x08,0x20,0x20,0x08 }, { 0x88,0x00,0x88,0x00 }    /* ...1...1...1...1 */
  623.     };
  624.  
  625.  
  626.     sega_decode(xortable);
  627. }
  628.  
  629.  
  630. void pitfall2_decode(void)
  631. {
  632.     static const unsigned char xortable[32][4] =
  633.     {
  634.         /*       opcode                   data                     address      */
  635.         /*  A    B    C    D         A    B    C    D                           */
  636.         { 0xa0,0x88,0x88,0xa0 }, { 0xa0,0x88,0x88,0xa0 },    /* ...0...0...0...0 */
  637.         { 0x08,0x80,0x08,0x80 }, { 0x28,0xa0,0x00,0x88 },    /* ...0...0...0...1 */
  638.         { 0xa0,0x88,0x88,0xa0 }, { 0xa0,0x88,0x88,0xa0 },    /* ...0...0...1...0 */
  639.         { 0xa0,0xa0,0x00,0x00 }, { 0xa0,0xa0,0x00,0x00 },    /* ...0...0...1...1 */
  640.         { 0xa0,0x88,0x88,0xa0 }, { 0x20,0x08,0x80,0xa8 },    /* ...0...1...0...0 */
  641.         { 0x28,0xa0,0x00,0x88 }, { 0x20,0x08,0x80,0xa8 },    /* ...0...1...0...1 */
  642.         { 0xa0,0xa0,0x00,0x00 }, { 0xa0,0xa0,0x00,0x00 },    /* ...0...1...1...0 */
  643.         { 0x28,0xa0,0x00,0x88 }, { 0xa0,0xa0,0x00,0x00 },    /* ...0...1...1...1 */
  644.         { 0x20,0x08,0x80,0xa8 }, { 0x80,0x80,0x80,0x80 },    /* ...1...0...0...0 */
  645.         { 0x80,0x80,0x80,0x80 }, { 0x80,0x80,0x80,0x80 },    /* ...1...0...0...1 */
  646.         { 0xa0,0xa0,0x00,0x00 }, { 0xa0,0x88,0x88,0xa0 },    /* ...1...0...1...0 */
  647.         { 0x80,0x80,0x80,0x80 }, { 0x28,0xa0,0x00,0x88 },    /* ...1...0...1...1 */
  648.         { 0x20,0x08,0x80,0xa8 }, { 0x80,0x80,0x80,0x80 },    /* ...1...1...0...0 */
  649.         { 0x80,0x80,0x80,0x80 }, { 0x20,0x08,0x80,0xa8 },    /* ...1...1...0...1 */
  650.         { 0xa0,0xa0,0x00,0x00 }, { 0xa0,0x88,0x88,0xa0 },    /* ...1...1...1...0 */
  651.         { 0x80,0x80,0x80,0x80 }, { 0x28,0xa0,0x00,0x88 }    /* ...1...1...1...1 */
  652.     };
  653.  
  654.  
  655.     sega_decode(xortable);
  656. }
  657.  
  658.  
  659. void nprinces_decode(void)
  660. {
  661.     static const unsigned char xortable[32][4] =
  662.     {
  663.         /*       opcode                   data                     address      */
  664.         /*  A    B    C    D         A    B    C    D                           */
  665.         { 0x08,0x80,0x20,0xa8 }, { 0xa0,0x28,0xa0,0x28 },    /* ...0...0...0...0 */
  666.         { 0xa8,0xa8,0x08,0x08 }, { 0x88,0xa0,0xa0,0x88 },    /* ...0...0...0...1 */
  667.         { 0x88,0x88,0x28,0x28 }, { 0x28,0x00,0x88,0xa0 },    /* ...0...0...1...0 */
  668.         { 0x88,0xa0,0xa0,0x88 }, { 0x28,0x00,0x88,0xa0 },    /* ...0...0...1...1 */
  669.         { 0x88,0xa0,0xa0,0x88 }, { 0xa0,0x28,0xa0,0x28 },    /* ...0...1...0...0 */
  670.         { 0xa8,0xa8,0x08,0x08 }, { 0xa8,0xa8,0x08,0x08 },    /* ...0...1...0...1 */
  671.         { 0x88,0x88,0x28,0x28 }, { 0x88,0xa0,0xa0,0x88 },    /* ...0...1...1...0 */
  672.         { 0x88,0xa0,0xa0,0x88 }, { 0x88,0xa0,0xa0,0x88 },    /* ...0...1...1...1 */
  673.         { 0xa0,0x28,0xa0,0x28 }, { 0xa0,0x28,0xa0,0x28 },    /* ...1...0...0...0 */
  674.         { 0x08,0x80,0x20,0xa8 }, { 0x28,0x00,0x88,0xa0 },    /* ...1...0...0...1 */
  675.         { 0x88,0xa0,0xa0,0x88 }, { 0x88,0x88,0x28,0x28 },    /* ...1...0...1...0 */
  676.         { 0x88,0xa0,0xa0,0x88 }, { 0x28,0x00,0x88,0xa0 },    /* ...1...0...1...1 */
  677.         { 0x88,0xa0,0xa0,0x88 }, { 0x88,0xa0,0xa0,0x88 },    /* ...1...1...0...0 */
  678.         { 0x88,0xa0,0xa0,0x88 }, { 0x88,0xa0,0xa0,0x88 },    /* ...1...1...0...1 */
  679.         { 0x88,0x88,0x28,0x28 }, { 0x88,0x88,0x28,0x28 },    /* ...1...1...1...0 */
  680.         { 0x08,0x80,0x20,0xa8 }, { 0x28,0x00,0x88,0xa0 }    /* ...1...1...1...1 */
  681.     };
  682.  
  683.  
  684.     sega_decode(xortable);
  685. }
  686.  
  687.  
  688. void seganinj_decode(void)
  689. {
  690.     static const unsigned char xortable[32][4] =
  691.     {
  692.         /*       opcode                   data                     address      */
  693.         /*  A    B    C    D         A    B    C    D                           */
  694.         { 0x88,0xa0,0xa0,0x88 }, { 0x88,0x00,0xa0,0x28 },    /* ...0...0...0...0 */
  695.         { 0x28,0xa0,0x28,0xa0 }, { 0xa0,0xa0,0xa0,0xa0 },    /* ...0...0...0...1 */
  696.         { 0xa8,0xa8,0x08,0x08 }, { 0xa8,0xa8,0x08,0x08 },    /* ...0...0...1...0 */
  697.         { 0x28,0xa0,0x28,0xa0 }, { 0xa0,0xa0,0xa0,0xa0 },    /* ...0...0...1...1 */
  698.         { 0x28,0x00,0x88,0xa0 }, { 0x28,0x00,0x88,0xa0 },    /* ...0...1...0...0 */
  699.         { 0x28,0xa0,0x28,0xa0 }, { 0x88,0x00,0xa0,0x28 },    /* ...0...1...0...1 */
  700.         { 0x28,0x00,0x88,0xa0 }, { 0x28,0x00,0x88,0xa0 },    /* ...0...1...1...0 */
  701.         { 0x28,0xa0,0x28,0xa0 }, { 0xa8,0xa8,0x08,0x08 },    /* ...0...1...1...1 */
  702.         { 0x88,0x00,0xa0,0x28 }, { 0x88,0xa0,0xa0,0x88 },    /* ...1...0...0...0 */
  703.         { 0xa0,0xa0,0xa0,0xa0 }, { 0x28,0xa0,0x28,0xa0 },    /* ...1...0...0...1 */
  704.         { 0xa8,0xa8,0x08,0x08 }, { 0x88,0xa0,0xa0,0x88 },    /* ...1...0...1...0 */
  705.         { 0xa8,0xa8,0x08,0x08 }, { 0x28,0xa0,0x28,0xa0 },    /* ...1...0...1...1 */
  706.         { 0x28,0x00,0x88,0xa0 }, { 0x88,0xa0,0xa0,0x88 },    /* ...1...1...0...0 */
  707.         { 0x28,0x00,0x88,0xa0 }, { 0x28,0x00,0x88,0xa0 },    /* ...1...1...0...1 */
  708.         { 0x88,0xa0,0xa0,0x88 }, { 0x88,0xa0,0xa0,0x88 },    /* ...1...1...1...0 */
  709.         { 0xa8,0xa8,0x08,0x08 }, { 0x28,0x00,0x88,0xa0 }    /* ...1...1...1...1 */
  710.     };
  711.  
  712.  
  713.     sega_decode(xortable);
  714. }
  715.  
  716.  
  717. void imsorry_decode(void)
  718. {
  719.     static const unsigned char xortable[32][4] =
  720.     {
  721.         /*       opcode                   data                     address      */
  722.         /*  A    B    C    D         A    B    C    D                           */
  723.         { 0x88,0x00,0xa0,0x28 }, { 0x00,0x28,0xa0,0x88 },    /* ...0...0...0...0 */
  724.         { 0x00,0x28,0xa0,0x88 }, { 0x88,0x00,0xa0,0x28 },    /* ...0...0...0...1 */
  725.         { 0x88,0x00,0x88,0x00 }, { 0x00,0x28,0xa0,0x88 },    /* ...0...0...1...0 */
  726.         { 0x00,0x28,0xa0,0x88 }, { 0x88,0x00,0x88,0x00 },    /* ...0...0...1...1 */
  727.         { 0x00,0x28,0xa0,0x88 }, { 0x08,0x08,0xa8,0xa8 },    /* ...0...1...0...0 */
  728.         { 0x00,0x28,0xa0,0x88 }, { 0x20,0x20,0x80,0x80 },    /* ...0...1...0...1 */
  729.         { 0x20,0x20,0x80,0x80 }, { 0x00,0x28,0xa0,0x88 },    /* ...0...1...1...0 */
  730.         { 0x20,0x20,0x80,0x80 }, { 0x88,0x00,0x88,0x00 },    /* ...0...1...1...1 */
  731.         { 0x88,0x00,0xa0,0x28 }, { 0x08,0x08,0xa8,0xa8 },    /* ...1...0...0...0 */
  732.         { 0x08,0x08,0xa8,0xa8 }, { 0x88,0x00,0xa0,0x28 },    /* ...1...0...0...1 */
  733.         { 0x08,0x20,0x20,0x08 }, { 0x08,0x20,0x20,0x08 },    /* ...1...0...1...0 */
  734.         { 0x88,0x00,0xa0,0x28 }, { 0x08,0x20,0x20,0x08 },    /* ...1...0...1...1 */
  735.         { 0x08,0x20,0x20,0x08 }, { 0x08,0x08,0xa8,0xa8 },    /* ...1...1...0...0 */
  736.         { 0x08,0x20,0x20,0x08 }, { 0x20,0x20,0x80,0x80 },    /* ...1...1...0...1 */
  737.         { 0x20,0x20,0x80,0x80 }, { 0x08,0x20,0x20,0x08 },    /* ...1...1...1...0 */
  738.         { 0x20,0x20,0x80,0x80 }, { 0x08,0x20,0x20,0x08 }    /* ...1...1...1...1 */
  739.     };
  740.  
  741.  
  742.     sega_decode(xortable);
  743. }
  744.  
  745.  
  746. void teddybb_decode(void)
  747. {
  748.     static const unsigned char xortable[32][4] =
  749.     {
  750.         /*       opcode                   data                     address      */
  751.         /*  A    B    C    D         A    B    C    D                           */
  752.         { 0x20,0x20,0x20,0x20 }, { 0x80,0x08,0x80,0x08 },    /* ...0...0...0...0 */
  753.         { 0x20,0x20,0x20,0x20 }, { 0xa0,0xa0,0x00,0x00 },    /* ...0...0...0...1 */
  754.         { 0x28,0x00,0x88,0xa0 }, { 0xa0,0x88,0x88,0xa0 },    /* ...0...0...1...0 */
  755.         { 0xa0,0xa0,0x00,0x00 }, { 0xa0,0x88,0x88,0xa0 },    /* ...0...0...1...1 */
  756.         { 0x20,0x20,0x20,0x20 }, { 0x28,0x00,0x88,0xa0 },    /* ...0...1...0...0 */
  757.         { 0xa0,0xa0,0x00,0x00 }, { 0xa0,0xa0,0x00,0x00 },    /* ...0...1...0...1 */
  758.         { 0xa0,0x88,0x88,0xa0 }, { 0x28,0x00,0x88,0xa0 },    /* ...0...1...1...0 */
  759.         { 0xa0,0xa0,0x00,0x00 }, { 0x28,0x00,0x88,0xa0 },    /* ...0...1...1...1 */
  760.         { 0x80,0x08,0x80,0x08 }, { 0x80,0x08,0x80,0x08 },    /* ...1...0...0...0 */
  761.         { 0xa0,0x28,0x88,0x00 }, { 0xa0,0xa0,0x00,0x00 },    /* ...1...0...0...1 */
  762.         { 0xa0,0x28,0x88,0x00 }, { 0xa0,0x88,0x88,0xa0 },    /* ...1...0...1...0 */
  763.         { 0xa0,0x88,0x88,0xa0 }, { 0xa0,0x88,0x88,0xa0 },    /* ...1...0...1...1 */
  764.         { 0x80,0x08,0x80,0x08 }, { 0x20,0x20,0x20,0x20 },    /* ...1...1...0...0 */
  765.         { 0xa0,0xa0,0x00,0x00 }, { 0xa0,0x28,0x88,0x00 },    /* ...1...1...0...1 */
  766.         { 0x80,0x08,0x80,0x08 }, { 0xa0,0x88,0x88,0xa0 },    /* ...1...1...1...0 */
  767.         { 0xa0,0xa0,0x00,0x00 }, { 0xa0,0x28,0x88,0x00 }    /* ...1...1...1...1 */
  768.     };
  769.  
  770.  
  771.     sega_decode(xortable);
  772. }
  773.  
  774.  
  775. void hvymetal_decode(void)
  776. {
  777.     static const unsigned char xortable[32][4] =
  778.     {
  779.         /*       opcode                   data                     address      */
  780.         /*  A    B    C    D         A    B    C    D                           */
  781.         { 0x88,0xa0,0xa0,0x88 }, { 0xa0,0x88,0x88,0xa0 },    /* ...0...0...0...0 */
  782.         { 0x88,0xa0,0xa0,0x88 }, { 0x88,0x88,0x28,0x28 },    /* ...0...0...0...1 */
  783.         { 0xa0,0x88,0x88,0xa0 }, { 0x88,0xa0,0xa0,0x88 },    /* ...0...0...1...0 */
  784.         { 0x88,0xa0,0xa0,0x88 }, { 0x88,0x88,0x28,0x28 },    /* ...0...0...1...1 */
  785.         { 0xa0,0x88,0x88,0xa0 }, { 0x88,0x88,0x28,0x28 },    /* ...0...1...0...0 */
  786.         { 0x88,0x88,0x28,0x28 }, { 0x88,0x88,0x28,0x28 },    /* ...0...1...0...1 */
  787.         { 0xa0,0x88,0x88,0xa0 }, { 0x88,0x88,0x28,0x28 },    /* ...0...1...1...0 */
  788.         { 0x88,0x88,0x28,0x28 }, { 0x28,0x00,0x88,0xa0 },    /* ...0...1...1...1 */
  789.         { 0xa0,0x28,0x88,0x00 }, { 0x88,0xa0,0xa0,0x88 },    /* ...1...0...0...0 */
  790.         { 0xa0,0x28,0x88,0x00 }, { 0x88,0xa0,0xa0,0x88 },    /* ...1...0...0...1 */
  791.         { 0xa0,0x28,0x88,0x00 }, { 0x88,0xa0,0xa0,0x88 },    /* ...1...0...1...0 */
  792.         { 0x88,0xa0,0xa0,0x88 }, { 0x28,0x00,0x88,0xa0 },    /* ...1...0...1...1 */
  793.         { 0x28,0xa0,0x28,0xa0 }, { 0xa0,0x28,0x88,0x00 },    /* ...1...1...0...0 */
  794.         { 0xa0,0x28,0x88,0x00 }, { 0x28,0xa0,0x28,0xa0 },    /* ...1...1...0...1 */
  795.         { 0x28,0xa0,0x28,0xa0 }, { 0xa0,0x28,0x88,0x00 },    /* ...1...1...1...0 */
  796.         { 0x28,0x00,0x88,0xa0 }, { 0x28,0xa0,0x28,0xa0 }    /* ...1...1...1...1 */
  797.     };
  798.  
  799.  
  800.     sega_decode(xortable);
  801. }
  802.  
  803.  
  804. void myheroj_decode(void)
  805. {
  806.     static const unsigned char xortable[32][4] =
  807.     {
  808.         /*       opcode                   data                     address      */
  809.         /*  A    B    C    D         A    B    C    D                           */
  810.         { 0x20,0x08,0x80,0xa8 }, { 0x80,0xa8,0xa8,0x80 },    /* ...0...0...0...0 */
  811.         { 0x20,0x08,0x80,0xa8 }, { 0x80,0xa8,0xa8,0x80 },    /* ...0...0...0...1 */
  812.         { 0xa8,0xa8,0xa8,0xa8 }, { 0xa8,0xa8,0xa8,0xa8 },    /* ...0...0...1...0 */
  813.         { 0x08,0x80,0x20,0xa8 }, { 0x80,0xa8,0xa8,0x80 },    /* ...0...0...1...1 */
  814.         { 0x20,0x08,0x80,0xa8 }, { 0x28,0xa0,0x28,0xa0 },    /* ...0...1...0...0 */
  815.         { 0x20,0x08,0x80,0xa8 }, { 0x08,0x80,0x20,0xa8 },    /* ...0...1...0...1 */
  816.         { 0x28,0xa0,0x28,0xa0 }, { 0xa8,0xa8,0xa8,0xa8 },    /* ...0...1...1...0 */
  817.         { 0x08,0x80,0x20,0xa8 }, { 0xa8,0xa8,0xa8,0xa8 },    /* ...0...1...1...1 */
  818.         { 0x28,0xa0,0x28,0xa0 }, { 0x20,0x08,0x80,0xa8 },    /* ...1...0...0...0 */
  819.         { 0x80,0xa8,0xa8,0x80 }, { 0x20,0x08,0x80,0xa8 },    /* ...1...0...0...1 */
  820.         { 0x80,0xa8,0xa8,0x80 }, { 0x80,0xa8,0xa8,0x80 },    /* ...1...0...1...0 */
  821.         { 0xa8,0xa8,0xa8,0xa8 }, { 0x80,0xa8,0xa8,0x80 },    /* ...1...0...1...1 */
  822.         { 0x88,0x88,0x28,0x28 }, { 0x88,0x88,0x28,0x28 },    /* ...1...1...0...0 */
  823.         { 0x88,0x88,0x28,0x28 }, { 0x08,0x80,0x20,0xa8 },    /* ...1...1...0...1 */
  824.         { 0x88,0x88,0x28,0x28 }, { 0xa8,0xa8,0xa8,0xa8 },    /* ...1...1...1...0 */
  825.         { 0x88,0x88,0x28,0x28 }, { 0xa8,0xa8,0xa8,0xa8 }    /* ...1...1...1...1 */
  826.     };
  827.  
  828.  
  829.     sega_decode(xortable);
  830. }
  831.  
  832.  
  833. /******************************************************************************
  834.  
  835.   4D Warriors
  836.  
  837.   This encryption is quite different from the standard one. It is still
  838.   a XOR scheme, but the value to use for the XOR is chosen differently, and
  839.   the affected bits are D0, D2, D4 and D6 instead of D3, D5 and D7.
  840.  
  841.   The translation table depends on A0, A3, A6, A9, A12 and A14; however A0, A3
  842.   and A6 only select some fixed additional XOR, so there are only 8 really
  843.   different tables.
  844.  
  845.   There are no separate tables for data and opcodes: the opcodes are just XORed
  846.   with an additional 0x40. To make it a little more complicated, however, data
  847.   picks its XOR value not from the line given by the address but from the one
  848.   below. For example if you are decoding a byte at address .1.0..1..0..1..0,
  849.   you pick the XOR value as if you were at address .1.0..1..0..1..1 (note that
  850.   I'm not talking about the rows of the xortable below, but of the "logical"
  851.   ones which are generated by them with the additional fixed XORs selected by
  852.   A0, A3 and A6).
  853.  
  854. ******************************************************************************/
  855.  
  856. void fdwarrio_decode(void)
  857. {
  858.     static const unsigned char xortable[8+1][8] =
  859.     {
  860.         /* note how the first lines are highly repetitive, while the */
  861.         /* last ones get more and more unique. */
  862.         { 0x00,0x00,0x14,0x14,0x14,0x14,0x00,0x00 },    /* .0.0..0..x..x..x */
  863.         { 0x00,0x11,0x00,0x11,0x11,0x00,0x11,0x00 },    /* .0.0..1..x..x..x */
  864.         { 0x00,0x05,0x05,0x00,0x00,0x05,0x05,0x00 },    /* .0.1..0..x..x..x */
  865.         { 0x00,0x00,0x44,0x44,0x14,0x14,0x50,0x50 },    /* .0.1..1..x..x..x */
  866.         { 0x00,0x00,0x14,0x14,0x50,0x50,0x44,0x44 },    /* .1.0..0..x..x..x */
  867.         { 0x00,0x05,0x05,0x00,0x50,0x55,0x55,0x50 },    /* .1.0..1..x..x..x */
  868.         { 0x00,0x11,0x05,0x14,0x14,0x05,0x11,0x00 },    /* .1.1..0..x..x..x */
  869.         { 0x00,0x41,0x05,0x44,0x14,0x55,0x11,0x50 },    /* .1.1..1..x..x..x */
  870.         { 0x00,0x11,0x05,0x14,0x50,0x41,0x55,0x44 }        /* extra line for data decode */
  871.     };
  872.     int A;
  873.     unsigned char *rom = memory_region(REGION_CPU1);
  874.     int diff = memory_region_length(REGION_CPU1) / 2;
  875.  
  876.  
  877.     memory_set_opcode_base(0,rom+diff);
  878.  
  879.     for (A = 0x0000;A < 0x8000;A++)
  880.     {
  881.         int row,col;
  882.         unsigned char src;
  883.  
  884.  
  885.         src = rom[A];
  886.  
  887.         /* pick the translation table from bits 0, 3, 6, 9, 12 and 14 of the address */
  888.         row = (A & 1) + (((A >> 3) & 1) << 1) + (((A >> 6) & 1) << 2)
  889.                 + (((A >> 9) & 1) << 3) + (((A >> 12) & 1) << 4) + (((A >> 14) & 1) << 5);
  890.  
  891.         /* pick the offset in the table from bits 0, 2, 4 and 6 of the source data */
  892.         col = ((src >> 0) & 1) + (((src >> 2) & 1) << 1) + (((src >> 4) & 1) << 2);
  893.         /* the bottom half of the translation table is the mirror image of the top */
  894.         if (src & 0x40) col = 7 - col;
  895.  
  896.         /* decode the opcodes */
  897.         rom[A + diff] = src ^ xortable[row >> 3][col] ^ 0x40;
  898.         if (row & 1) rom[A + diff] ^= 0x10;
  899.         if (row & 2) rom[A + diff] ^= 0x04;
  900.         if (row & 4) rom[A + diff] ^= 0x01;
  901.  
  902.         /* decode the data */
  903.         row++;    /* the data XOR table is shifted by one position!!!! */
  904.         rom[A] = src ^ xortable[row >> 3][col];
  905.         if (row & 1) rom[A] ^= 0x10;
  906.         if (row & 2) rom[A] ^= 0x04;
  907.         if (row & 4) rom[A] ^= 0x01;
  908.     }
  909.  
  910.     /* copy the opcodes from the not encrypted part of the ROMs */
  911.     for (A = 0x8000;A < diff;A++)
  912.         rom[A + diff] = rom[A];
  913. }
  914.  
  915.  
  916.  
  917. /******************************************************************************
  918.  
  919.   Wonder Boy
  920.  
  921.   This is different again. It is similar to 4D Warriors - it affects the same
  922.   data bits and is selected by the same address lines, but I haven't been able
  923.   to find any regularities in the XOR table, so I'm using a huge 1024 bytes
  924.   array.
  925.  
  926. ******************************************************************************/
  927.  
  928. void wboy3_decode(void)
  929. {
  930.     /* not decoded yet! */
  931. }
  932.  
  933.  
  934. void wboy4_decode(void)
  935. {
  936.     static const unsigned char opcode_xortable[8*8][8] =
  937.     {
  938.         { 0x00,0x00,0x44,0x44,0x00,0x00,0x44,0x44 },    /* .0.0 ..0. .0.. 0..0 */
  939.         { 0x45,0x54,0x45,0x54,0x54,0x45,0x54,0x45 },    /* .0.0 ..0. .0.. 0..1 */
  940.         { 0x11,0x11,0x11,0x11,0x41,0x41,0x41,0x41 },    /* .0.0 ..0. .0.. 1..0 */
  941.         { 0x01,0x10,0x01,0x10,0x10,0x01,0x10,0x01 },    /* .0.0 ..0. .0.. 1..1 */
  942.         { 0x44,0x44,0x44,0x44,0x14,0x14,0x14,0x14 },    /* .0.0 ..0. .1.. 0..0 */
  943.         { 0x10,0x01,0x10,0x01,0x01,0x10,0x01,0x10 },    /* .0.0 ..0. .1.. 0..1 */
  944.         { 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55 },    /* .0.0 ..0. .1.. 1..0 */
  945.         { 0x05,0x05,0x11,0x11,0x11,0x11,0x05,0x05 },    /* .0.0 ..0. .1.. 1..1 */
  946.         { 0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41 },    /* .0.0 ..1. .0.. 0..0 */
  947.         { 0x14,0x14,0x00,0x00,0x00,0x00,0x14,0x14 },    /* .0.0 ..1. .0.. 0..1 */
  948.         { 0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04 },    /* .0.0 ..1. .0.. 1..0 */
  949.         { 0x40,0x40,0x54,0x54,0x54,0x54,0x40,0x40 },    /* .0.0 ..1. .0.. 1..1 */
  950.         { 0x15,0x15,0x51,0x51,0x01,0x01,0x45,0x45 },    /* .0.0 ..1. .1.. 0..0 */
  951.         { 0x51,0x10,0x51,0x10,0x51,0x10,0x51,0x10 },    /* .0.0 ..1. .1.. 0..1 */
  952.         { 0x01,0x01,0x45,0x45,0x15,0x15,0x51,0x51 },    /* .0.0 ..1. .1.. 1..0 */
  953.         { 0x44,0x05,0x44,0x05,0x44,0x05,0x44,0x05 },    /* .0.0 ..1. .1.. 1..1 */
  954.         { 0x10,0x10,0x54,0x54,0x04,0x04,0x40,0x40 },    /* .0.1 ..0. .0.. 0..0 */
  955.         { 0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41 },    /* .0.1 ..0. .0.. 0..1 */
  956.         { 0x45,0x40,0x40,0x45,0x45,0x40,0x40,0x45 },    /* .0.1 ..0. .0.. 1..0 */
  957.         { 0x11,0x11,0x55,0x55,0x11,0x11,0x55,0x55 },    /* .0.1 ..0. .0.. 1..1 */
  958.         { 0x54,0x51,0x51,0x54,0x54,0x51,0x51,0x54 },    /* .0.1 ..0. .1.. 0..0 */
  959.         { 0x04,0x04,0x40,0x40,0x04,0x04,0x40,0x40 },    /* .0.1 ..0. .1.. 0..1 */
  960.         { 0x40,0x45,0x45,0x40,0x40,0x45,0x45,0x40 },    /* .0.1 ..0. .1.. 1..0 */
  961.         { 0x15,0x15,0x15,0x15,0x45,0x45,0x45,0x45 },    /* .0.1 ..0. .1.. 1..1 */
  962.         { 0x05,0x14,0x05,0x14,0x14,0x05,0x14,0x05 },    /* .0.1 ..1. .0.. 0..0 */
  963.         { 0x41,0x41,0x41,0x41,0x11,0x11,0x11,0x11 },    /* .0.1 ..1. .0.. 0..1 */
  964.         { 0x14,0x05,0x14,0x05,0x05,0x14,0x05,0x14 },    /* .0.1 ..1. .0.. 1..0 */
  965.         { 0x50,0x50,0x50,0x50,0x00,0x00,0x00,0x00 },    /* .0.1 ..1. .0.. 1..1 */
  966.         { 0x00,0x11,0x00,0x11,0x11,0x00,0x11,0x00 },    /* .0.1 ..1. .1.. 0..0 */
  967.         { 0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45 },    /* .0.1 ..1. .1.. 0..1 */
  968.         { 0x11,0x11,0x05,0x05,0x05,0x05,0x11,0x11 },    /* .0.1 ..1. .1.. 1..0 */
  969.         { 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01 },    /* .0.1 ..1. .1.. 1..1 */
  970.         { 0x00,0x11,0x05,0x14,0x14,0x05,0x11,0x00 },    /* .1.0 ..0. .0.. 0..0 */
  971.         { 0x45,0x04,0x40,0x01,0x45,0x04,0x40,0x01 },    /* .1.0 ..0. .0.. 0..1 */
  972.         { 0x11,0x14,0x14,0x11,0x41,0x44,0x44,0x41 },    /* .1.0 ..0. .0.. 1..0 */
  973.         { 0x01,0x40,0x04,0x45,0x01,0x40,0x04,0x45 },    /* .1.0 ..0. .0.. 1..1 */
  974.         { 0x44,0x41,0x41,0x44,0x14,0x11,0x11,0x14 },    /* .1.0 ..0. .1.. 0..0 */
  975.         { 0x10,0x51,0x15,0x54,0x10,0x51,0x15,0x54 },    /* .1.0 ..0. .1.. 0..1 */
  976.         { 0x55,0x55,0x41,0x41,0x05,0x05,0x11,0x11 },    /* .1.0 ..0. .1.. 1..0 */
  977.         { 0x05,0x14,0x00,0x11,0x55,0x44,0x50,0x41 },    /* .1.0 ..0. .1.. 1..1 */
  978.         { 0x41,0x41,0x55,0x55,0x11,0x11,0x05,0x05 },    /* .1.0 ..1. .0.. 0..0 */
  979.         { 0x14,0x05,0x11,0x00,0x44,0x55,0x41,0x50 },    /* .1.0 ..1. .0.. 0..1 */
  980.         { 0x04,0x04,0x10,0x10,0x54,0x54,0x40,0x40 },    /* .1.0 ..1. .0.. 1..0 */
  981.         { 0x40,0x51,0x45,0x54,0x10,0x01,0x15,0x04 },    /* .1.0 ..1. .0.. 1..1 */
  982.         { 0x15,0x10,0x51,0x54,0x04,0x01,0x40,0x45 },    /* .1.0 ..1. .1.. 0..0 */
  983.         { 0x51,0x10,0x54,0x15,0x45,0x04,0x40,0x01 },    /* .1.0 ..1. .1.. 0..1 */
  984.         { 0x01,0x04,0x45,0x40,0x10,0x15,0x54,0x51 },    /* .1.0 ..1. .1.. 1..0 */
  985.         { 0x44,0x05,0x41,0x00,0x50,0x11,0x55,0x14 },    /* .1.0 ..1. .1.. 1..1 */
  986.         /* the following are all FF because there is no code to decode */
  987.         { 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff },    /* .1.1 ..0. .0.. 0..0 */
  988.         { 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff },    /* .1.1 ..0. .0.. 0..1 */
  989.         { 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff },    /* .1.1 ..0. .0.. 1..0 */
  990.         { 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff },    /* .1.1 ..0. .0.. 1..1 */
  991.         { 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff },    /* .1.1 ..0. .1.. 0..0 */
  992.         { 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff },    /* .1.1 ..0. .1.. 0..1 */
  993.         { 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff },    /* .1.1 ..0. .1.. 1..0 */
  994.         { 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff },    /* .1.1 ..0. .1.. 1..1 */
  995.         { 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff },    /* .1.1 ..1. .0.. 0..0 */
  996.         { 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff },    /* .1.1 ..1. .0.. 0..1 */
  997.         { 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff },    /* .1.1 ..1. .0.. 1..0 */
  998.         { 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff },    /* .1.1 ..1. .0.. 1..1 */
  999.         { 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff },    /* .1.1 ..1. .1.. 0..0 */
  1000.         { 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff },    /* .1.1 ..1. .1.. 0..1 */
  1001.         { 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff },    /* .1.1 ..1. .1.. 1..0 */
  1002.         { 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff },    /* .1.1 ..1. .1.. 1..1 */
  1003.     };
  1004.     static const unsigned char data_xortable[8*8][8] =
  1005.     {
  1006.         { 0x55,0x14,0x55,0x14,0x55,0x14,0x55,0x14 },    /* .0.0 ..0. .0.. 0..0 */
  1007.         { 0x05,0x05,0x41,0x41,0x11,0x11,0x55,0x55 },    /* .0.0 ..0. .0.. 0..1 */
  1008.         { 0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00 },    /* .0.0 ..0. .0.. 1..0 */
  1009.         { 0x14,0x14,0x50,0x50,0x00,0x00,0x44,0x44 },    /* .0.0 ..0. .0.. 1..1 */
  1010.         { 0x50,0x11,0x50,0x11,0x50,0x11,0x50,0x11 },    /* .0.0 ..0. .1.. 0..0 */
  1011.         { 0x00,0x00,0x44,0x44,0x14,0x14,0x50,0x50 },    /* .0.0 ..0. .1.. 0..1 */
  1012.         { 0x15,0x15,0x51,0x51,0x15,0x15,0x51,0x51 },    /* .0.0 ..0. .1.. 1..0 */
  1013.         { 0x51,0x54,0x54,0x51,0x51,0x54,0x54,0x51 },    /* .0.0 ..0. .1.. 1..1 */
  1014.         { 0x01,0x01,0x45,0x45,0x01,0x01,0x45,0x45 },    /* .0.0 ..1. .0.. 0..0 */
  1015.         { 0x44,0x41,0x41,0x44,0x44,0x41,0x41,0x44 },    /* .0.0 ..1. .0.. 0..1 */
  1016.         { 0x10,0x10,0x54,0x54,0x10,0x10,0x54,0x54 },    /* .0.0 ..1. .0.. 1..0 */
  1017.         { 0x55,0x44,0x55,0x44,0x44,0x55,0x44,0x55 },    /* .0.0 ..1. .0.. 1..1 */
  1018.         { 0x05,0x05,0x05,0x05,0x55,0x55,0x55,0x55 },    /* .0.0 ..1. .1.. 0..0 */
  1019.         { 0x11,0x00,0x11,0x00,0x00,0x11,0x00,0x11 },    /* .0.0 ..1. .1.. 0..1 */
  1020.         { 0x54,0x54,0x54,0x54,0x04,0x04,0x04,0x04 },    /* .0.0 ..1. .1.. 1..0 */
  1021.         { 0x04,0x15,0x04,0x15,0x15,0x04,0x15,0x04 },    /* .0.0 ..1. .1.. 1..1 */
  1022.         { 0x40,0x40,0x40,0x40,0x10,0x10,0x10,0x10 },    /* .0.1 ..0. .0.. 0..0 */
  1023.         { 0x15,0x15,0x01,0x01,0x01,0x01,0x15,0x15 },    /* .0.1 ..0. .0.. 0..1 */
  1024.         { 0x51,0x51,0x51,0x51,0x51,0x51,0x51,0x51 },    /* .0.1 ..0. .0.. 1..0 */
  1025.         { 0x01,0x01,0x15,0x15,0x15,0x15,0x01,0x01 },    /* .0.1 ..0. .0.. 1..1 */
  1026.         { 0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14 },    /* .0.1 ..0. .1.. 0..0 */
  1027.         { 0x50,0x50,0x44,0x44,0x44,0x44,0x50,0x50 },    /* .0.1 ..0. .1.. 0..1 */
  1028.         { 0x00,0x00,0x14,0x14,0x50,0x50,0x44,0x44 },    /* .0.1 ..0. .1.. 1..0 */
  1029.         { 0x45,0x04,0x45,0x04,0x45,0x04,0x45,0x04 },    /* .0.1 ..0. .1.. 1..1 */
  1030.         { 0x11,0x11,0x55,0x55,0x05,0x05,0x41,0x41 },    /* .0.1 ..1. .0.. 0..0 */
  1031.         { 0x54,0x15,0x54,0x15,0x54,0x15,0x54,0x15 },    /* .0.1 ..1. .0.. 0..1 */
  1032.         { 0x04,0x04,0x40,0x40,0x10,0x10,0x54,0x54 },    /* .0.1 ..1. .0.. 1..0 */
  1033.         { 0x10,0x51,0x10,0x51,0x10,0x51,0x10,0x51 },    /* .0.1 ..1. .0.. 1..1 */
  1034.         { 0x55,0x50,0x50,0x55,0x55,0x50,0x50,0x55 },    /* .0.1 ..1. .1.. 0..0 */
  1035.         { 0x05,0x05,0x41,0x41,0x05,0x05,0x41,0x41 },    /* .0.1 ..1. .1.. 0..1 */
  1036.         { 0x41,0x44,0x44,0x41,0x41,0x44,0x44,0x41 },    /* .0.1 ..1. .1.. 1..0 */
  1037.         { 0x14,0x14,0x50,0x50,0x14,0x14,0x50,0x50 },    /* .0.1 ..1. .1.. 1..1 */
  1038.         { 0x55,0x14,0x50,0x11,0x41,0x00,0x44,0x05 },    /* .1.0 ..0. .0.. 0..0 */
  1039.         { 0x05,0x00,0x41,0x44,0x14,0x11,0x50,0x55 },    /* .1.0 ..0. .0.. 0..1 */
  1040.         { 0x41,0x00,0x44,0x05,0x55,0x14,0x50,0x11 },    /* .1.0 ..0. .0.. 1..0 */
  1041.         { 0x14,0x11,0x50,0x55,0x05,0x00,0x41,0x44 },    /* .1.0 ..0. .0.. 1..1 */
  1042.         { 0x50,0x11,0x55,0x14,0x44,0x05,0x41,0x00 },    /* .1.0 ..0. .1.. 0..0 */
  1043.         { 0x00,0x05,0x44,0x41,0x11,0x14,0x55,0x50 },    /* .1.0 ..0. .1.. 0..1 */
  1044.         { 0x15,0x04,0x10,0x01,0x01,0x10,0x04,0x15 },    /* .1.0 ..0. .1.. 1..0 */
  1045.         { 0x51,0x54,0x45,0x40,0x40,0x45,0x54,0x51 },    /* .1.0 ..0. .1.. 1..1 */
  1046.         { 0x01,0x10,0x04,0x15,0x15,0x04,0x10,0x01 },    /* .1.0 ..1. .0.. 0..0 */
  1047.         { 0x44,0x41,0x50,0x55,0x55,0x50,0x41,0x44 },    /* .1.0 ..1. .0.. 0..1 */
  1048.         { 0x10,0x01,0x15,0x04,0x04,0x15,0x01,0x10 },    /* .1.0 ..1. .0.. 1..0 */
  1049.         { 0x55,0x14,0x50,0x11,0x55,0x14,0x50,0x11 },    /* .1.0 ..1. .0.. 1..1 */
  1050.         { 0x05,0x00,0x00,0x05,0x55,0x50,0x50,0x55 },    /* .1.0 ..1. .1.. 0..0 */
  1051.         { 0x11,0x50,0x14,0x55,0x11,0x50,0x14,0x55 },    /* .1.0 ..1. .1.. 0..1 */
  1052.         { 0x54,0x51,0x51,0x54,0x04,0x01,0x01,0x04 },    /* .1.0 ..1. .1.. 1..0 */
  1053.         { 0x04,0x45,0x01,0x40,0x04,0x45,0x01,0x40 },    /* .1.0 ..1. .1.. 1..1 */
  1054.         { 0x40,0x45,0x45,0x40,0x10,0x15,0x15,0x10 },    /* .1.1 ..0. .0.. 0..0 */
  1055.         { 0x15,0x04,0x10,0x01,0x45,0x54,0x40,0x51 },    /* .1.1 ..0. .0.. 0..1 */
  1056.         { 0x51,0x51,0x45,0x45,0x01,0x01,0x15,0x15 },    /* .1.1 ..0. .0.. 1..0 */
  1057.         { 0x01,0x10,0x04,0x15,0x51,0x40,0x54,0x45 },    /* .1.1 ..0. .0.. 1..1 */
  1058.         { 0x14,0x14,0x00,0x00,0x44,0x44,0x50,0x50 },    /* .1.1 ..0. .1.. 0..0 */
  1059.         { 0x50,0x41,0x55,0x44,0x00,0x11,0x05,0x14 },    /* .1.1 ..0. .1.. 0..1 */
  1060.         { 0x00,0x41,0x00,0x41,0x11,0x50,0x11,0x50 },    /* .1.1 ..0. .1.. 1..0 */
  1061.         { 0x45,0x04,0x40,0x01,0x51,0x10,0x54,0x15 },    /* .1.1 ..0. .1.. 1..1 */
  1062.         { 0x11,0x14,0x55,0x50,0x00,0x05,0x44,0x41 },    /* .1.1 ..1. .0.. 0..0 */
  1063.         { 0x54,0x15,0x51,0x10,0x40,0x01,0x45,0x04 },    /* .1.1 ..1. .0.. 0..1 */
  1064.         { 0x04,0x01,0x40,0x45,0x15,0x10,0x51,0x54 },    /* .1.1 ..1. .0.. 1..0 */
  1065.         { 0x10,0x51,0x15,0x54,0x04,0x45,0x01,0x40 },    /* .1.1 ..1. .0.. 1..1 */
  1066.         { 0x55,0x50,0x41,0x44,0x44,0x41,0x50,0x55 },    /* .1.1 ..1. .1.. 0..0 */
  1067.         { 0x05,0x14,0x00,0x11,0x11,0x00,0x14,0x05 },    /* .1.1 ..1. .1.. 0..1 */
  1068.         { 0x41,0x44,0x55,0x50,0x50,0x55,0x44,0x41 },    /* .1.1 ..1. .1.. 1..0 */
  1069.         { 0x14,0x05,0x11,0x00,0x00,0x11,0x05,0x14 },    /* .1.1 ..1. .1.. 1..1 */
  1070.     };
  1071.     int A;
  1072.     unsigned char *rom = memory_region(REGION_CPU1);
  1073.     int diff = memory_region_length(REGION_CPU1) / 2;
  1074.  
  1075.  
  1076.     memory_set_opcode_base(0,rom+diff);
  1077.  
  1078.     for (A = 0x0000;A < 0x8000;A++)
  1079.     {
  1080.         int row,col;
  1081.         unsigned char src;
  1082.  
  1083.  
  1084.         src = rom[A];
  1085.  
  1086.         /* pick the translation table from bits 0, 3, 6, 9, 12 and 14 of the address */
  1087.         row = (A & 1) + (((A >> 3) & 1) << 1) + (((A >> 6) & 1) << 2)
  1088.                 + (((A >> 9) & 1) << 3) + (((A >> 12) & 1) << 4) + (((A >> 14) & 1) << 5);
  1089.  
  1090.         /* pick the offset in the table from bits 0, 2, 4 and 6 of the source data */
  1091.         col = ((src >> 0) & 1) + (((src >> 2) & 1) << 1) + (((src >> 4) & 1) << 2);
  1092.         /* the bottom half of the translation table is the mirror image of the top */
  1093.         if (src & 0x40) col = 7 - col;
  1094.  
  1095.         /* decode the opcodes */
  1096.         rom[A + diff] = src ^ opcode_xortable[row][col] ^ 0x00;
  1097.  
  1098.         /* decode the data */
  1099.         rom[A] = src ^ data_xortable[row][col];
  1100.     }
  1101.  
  1102.     /* copy the opcodes from the not encrypted part of the ROMs */
  1103.     for (A = 0x8000;A < diff;A++)
  1104.         rom[A + diff] = rom[A];
  1105. }
  1106.  
  1107.  
  1108. void gardia_decode(void)
  1109. {
  1110.     /* not decoded yet! */
  1111. }
  1112.